package cn.jinjimi.domain;

import cn.jinjimi.app.DefaultDispatcher;
import cn.jinjimi.app.DefaultExecutor;
import cn.jinjimi.domain.data.imp.AdvStoreImp;
import cn.jinjimi.domain.data.imp.AppStoreImp;
import cn.jinjimi.domain.data.imp.CardStoreImp;
import cn.jinjimi.domain.data.imp.ConfigStoreImp;
import cn.jinjimi.domain.data.imp.CustomerStoreImp;
import cn.jinjimi.domain.data.imp.FileStoreImp;
import cn.jinjimi.domain.data.imp.PosterStoreImp;
import cn.jinjimi.domain.data.imp.ReaderStoreImp;
import cn.jinjimi.domain.data.imp.TaskStoreImp;
import cn.jinjimi.domain.data.imp.UserStoreImp;
import cn.jinjimi.domain.store.AdvStore;
import cn.jinjimi.domain.store.AppStore;
import cn.jinjimi.domain.store.CardStore;
import cn.jinjimi.domain.store.ConfigStore;
import cn.jinjimi.domain.store.CustomerStore;
import cn.jinjimi.domain.store.FileStore;
import cn.jinjimi.domain.store.PosterStore;
import cn.jinjimi.domain.store.ReaderStore;
import cn.jinjimi.domain.store.TaskStore;
import cn.jinjimi.domain.store.UserStore;

import java.util.HashMap;
import java.util.Map;

/**
 * Created by zhenhua on 16/7/15.
 */
public class ServiceManager {

    private static Map<String, ServiceFetcher> SERVICES = new HashMap<>();

    private static Map<String, Object> CACHED = new HashMap<>();

    static {

        register(Executor.class, new ServiceFetcher() {
            @Override
            public Object getService() {
                return DefaultExecutor.get();
            }
        });

        register(Dispatcher.class, new ServiceFetcher() {
            @Override
            public Object getService() {
                return DefaultDispatcher.get();
            }
        });

        register(CustomerStore.class, new ServiceFetcher() {
            @Override
            public Object getService() {
                return new CustomerStoreImp();
            }
        });

        register(CardStore.class, new ServiceFetcher() {
            @Override
            public Object getService() {
                return new CardStoreImp();
            }
        });

        register(ConfigStore.class, new ServiceFetcher() {
            @Override
            public Object getService() {
                return new ConfigStoreImp();
            }
        });

        register(UserStore.class, new ServiceFetcher() {
            @Override
            public Object getService() {
                return new UserStoreImp();
            }
        });

        register(ReaderStore.class, new ServiceFetcher() {
            @Override
            public Object getService() {
                return new ReaderStoreImp();
            }
        });

        register(AppStore.class, new ServiceFetcher() {
            @Override
            public Object getService() {
                return new AppStoreImp();
            }
        });

        register(AdvStore.class, new ServiceFetcher() {
            @Override
            public Object getService() {
                return new AdvStoreImp();
            }
        });

        register(FileStore.class, new ServiceFetcher() {
            @Override
            public Object getService() {
                return new FileStoreImp();
            }
        });

        register(PosterStore.class, new ServiceFetcher() {
            @Override
            public Object getService() {
                return new PosterStoreImp();
            }
        });

        register(TaskStore.class, new ServiceFetcher() {
            @Override
            public Object getService() {
                return new TaskStoreImp();
            }
        });

    }

    public static void register(Class<?> tClass, ServiceFetcher fetcher) {
        SERVICES.put(tClass.getName(), fetcher);
    }

    @SuppressWarnings("unchecked")
    public static <T> T getService(Class<T> tClass) {

        T service = null;

        if (tClass != null) {
            //try 2 get cached service object.
            service = (T) CACHED.get(tClass.getName());

            //fetch a new service entry.
            if (service == null) {
                ServiceFetcher fetcher = SERVICES.get(tClass.getName());
                if (fetcher != null) {
                    service = (T) fetcher.getService();
                    CACHED.put(tClass.getName(), service);
                }
            }
        }

        return service;
    }

    public interface ServiceFetcher {
        Object getService();
    }
}
